mod config;
mod handlers;
mod middleware;
mod models;
mod routes;
mod services;

use axum::{
    routing::get,
    Router,
};
use sqlx::mysql::MySqlPoolOptions;
use std::net::SocketAddr;
use tower_http::cors::{Any, CorsLayer};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};

use crate::{
    config::Config, routes::{ai_routes, auth_routes, news_search_routes}, services::{AiService, NewsSearchService, UserService}
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化日志
    tracing_subscriber::registry()
        .with(EnvFilter::new(
            std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()),
        ))
        .with(tracing_subscriber::fmt::layer())
        .init();

    // 加载配置
    let config = Config::from_env();
    // 连接数据库
    let pool = MySqlPoolOptions::new()
        .max_connections(5)
        .connect(&config.database_url)
        .await?;

    // 检查是否需要运行数据库迁移
    let table_exists = sqlx::query("SHOW TABLES LIKE 'users'")
        .fetch_optional(&pool)
        .await?;
    if table_exists.is_none() {
        tracing::info!("数据库表不存在，正在运行迁移...");
        sqlx::migrate!("./migrations").run(&pool).await?;
        tracing::info!("数据库迁移完成");
    } else {
        tracing::info!("数据库表已存在，跳过迁移");
    }

    // 创建用户服务
    let user_service = UserService::new(pool.clone(), config.jwt_secret.clone());
    // 创建AI服务
    let ai_service = AiService::new(config.deepseek_api_key.clone(), pool.clone());
    // 创建新闻检索服务
    let news_search_service = NewsSearchService::new(config.news_xml_path.clone());

    // 配置CORS
    let cors = CorsLayer::new()
        .allow_origin(Any)
        .allow_methods(Any)
        .allow_headers(Any);

    // 创建路由
    let app = Router::new()
        .route("/", get(|| async { "YQFX Backend API" }))
        .nest("/api/auth", auth_routes(user_service.clone()))
        .nest("/api/ai", ai_routes(ai_service, user_service.clone()))
        .nest("/api/news_search", news_search_routes(news_search_service.clone(), user_service.clone()))
        .layer(cors);

    // 启动服务器
    let addr = SocketAddr::from(([127, 0, 0, 1], config.port));
    tracing::info!("服务器启动在 http://{}", addr);
    let listener = tokio::net::TcpListener::bind(addr).await?;
    axum::serve(listener, app).await?;

    Ok(())
}
